home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / haeberli / libcan / canvas.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  11.5 KB  |  573 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  *    canvas -
  19.  *        Basic support for creation an manipulation of canvases.
  20.  *
  21.  *                Paul Haeberli - 1991
  22.  *
  23.  *    exports
  24.  *
  25.     int round(v)
  26.     void initcanvas(c,xsize,ysize);
  27.     canvas *newcanvas(xsize,ysize)
  28.     canvas *imagetocanvas(name)
  29.     canvas *crudeimagetocanvas(name)
  30.     int canvastoimage(c,name)
  31.     void freecanvas(c)
  32.     canvas *clonecanvas(c)
  33.     void canvasflushfunc(c,func)
  34.     void flushcanvas(c)
  35.     void canvascopy(c,cc)
  36.     void touchcanvas(c)
  37.     unsigned long samplecanvas(c,pos,dofilter)
  38.     void markdirty(c,r,add)
  39.     void clearcanvas(c)
  40.     void framecanvas(c)
  41.     void copyto(scan,dcan)
  42.     canvas *subcanvas(c,x1,x2,y1,y2);
  43.     void copycanvas(scan,srct,dcan,drct,filter)
  44.     void printcanvas(c)
  45.  *
  46.  */
  47. #include "stdio.h"
  48. #include "canvas.h"
  49. #include "vect.h"
  50. #include "izoom.h"
  51. #include "math.h"
  52. #include "resource.h"
  53. #include "image.h"
  54.  
  55. void canvascopy();
  56. void touchcanvas();
  57. void copycanvas();
  58.  
  59. int round(v)
  60. float v;
  61. {
  62.     return ffloor(v+0.499);
  63. }
  64.  
  65. /*
  66.  *    canvas creation and free code 
  67.  *
  68.  */
  69. void initcanvas(c,xsize,ysize)
  70. canvas *c;
  71. int xsize, ysize;
  72. {
  73.     c->flushfunc = 0;
  74.     c->xsize = xsize;
  75.     c->ysize = ysize;
  76.     c->strokeno = 0;
  77.     c->area.xmin = 0;
  78.     c->area.xmax = c->xsize-1;
  79.     c->area.ymin = 0;
  80.     c->area.ymax = c->ysize-1;
  81.     c->undo = 0;
  82. }
  83.  
  84. #define TAGLEN    5
  85.  
  86. canvas *newcanvas(xsize,ysize)
  87. int xsize, ysize;
  88. {
  89.     canvas *c;
  90.     unsigned long *dptr;
  91.  
  92.     c = (canvas *)mymalloc(sizeof(canvas));
  93.     initcanvas(c,xsize,ysize);
  94.     c->data = (unsigned long *)mymalloc((xsize*ysize+TAGLEN)*sizeof(unsigned long));
  95.     addlongimgtag(c->data,xsize,ysize);
  96.     touchcanvas(c);
  97.     return c;
  98. }
  99.  
  100. canvas *imagetocanvas(name)
  101. char *name;
  102. {
  103.     int xsize, ysize;
  104.     canvas *c;
  105.  
  106.     sizeofimage(name,&xsize,&ysize);
  107.     c = (canvas *)mymalloc(sizeof(canvas));
  108.     initcanvas(c,xsize,ysize);
  109.     c->data = (unsigned long *)longimagedata(name);
  110.     touchcanvas(c);
  111.     return c;
  112. }
  113.  
  114. #define CRUDEPIX    (100)
  115. static short *rbuf, *gbuf, *bbuf, *abuf;
  116. static unsigned long *sdata;
  117. static int *offset;
  118.  
  119. canvas *crudeimagetocanvas(name)
  120. char *name;
  121. {
  122.     int xsize, ysize, zsize, totpix;
  123.     int cxsize, cysize, cxsize2, cysize2;
  124.     int x, y, ix, iy;
  125.     unsigned long *sptr;
  126.     canvas *c;
  127.     IMAGE *image;
  128.     
  129.     image = iopen(name,"r");
  130.     if(!image) {
  131.     fprintf(stderr,"can't open input file %s\n",name);
  132.     exit(1);
  133.     }
  134.     xsize = image->xsize;
  135.     ysize = image->ysize;
  136.     zsize = image->zsize;
  137.     totpix = xsize*ysize;
  138.     cxsize = xsize*sqrt(CRUDEPIX/(float)totpix)+0.5;
  139.     cysize = ysize*sqrt(CRUDEPIX/(float)totpix)+0.5;
  140.     if(cxsize<1) cxsize = 1;
  141.     if(cysize<1) cysize = 1;
  142. printf("csize %d %d\n",cxsize,cysize);
  143.     cxsize2 = cxsize>>1;
  144.     cysize2 = cysize>>1;
  145.     c = (canvas *)mymalloc(sizeof(canvas));
  146.     initcanvas(c,xsize,ysize);
  147.     rbuf = (short *)bufalloc(rbuf,xsize*sizeof(short));
  148.     gbuf = (short *)bufalloc(gbuf,xsize*sizeof(short));
  149.     bbuf = (short *)bufalloc(bbuf,xsize*sizeof(short));
  150.     abuf = (short *)bufalloc(abuf,xsize*sizeof(short));
  151.     sdata = (unsigned long *)bufalloc(sdata,cxsize*cysize*sizeof(long));
  152.     offset = (int *)bufalloc(offset,cxsize*sizeof(int));
  153.     sptr = sdata;
  154.     for(x=0; x<cxsize; x++) 
  155.     offset[x] = (x*xsize+cxsize2)/cxsize;
  156.     for(y=0; y<cysize; y++) {
  157.     iy = (y*ysize+cysize2)/cysize;
  158.     getrow(image,rbuf,iy,0);
  159.     if(zsize>=3) {
  160.         getrow(image,gbuf,iy,1);
  161.         getrow(image,bbuf,iy,2);
  162.         if(zsize>3) 
  163.         getrow(image,abuf,iy,3);
  164.     }
  165.     if(zsize<3) {
  166.         for(x=0; x<cxsize; x++) {
  167.         ix = offset[x];
  168.         *sptr++ = (0x10101*rbuf[ix])|0xff000000;
  169.         }
  170.     } else if(zsize == 3) {
  171.         for(x=0; x<cxsize; x++) {
  172.         ix = offset[x];
  173.         *sptr++ = ((rbuf[ix]<<0)+(gbuf[ix]<<8)+
  174.                         (bbuf[ix]<<16))|0xff000000;
  175.         }
  176.     } else {
  177.         for(x=0; x<cxsize; x++) {
  178.         ix = offset[x];
  179.         *sptr++ = ((rbuf[ix]<<0)+(gbuf[ix]<<8)+
  180.                 (bbuf[ix]<<16)+(abuf[ix]<<24));
  181.         }
  182.     }
  183.     }
  184.     iclose(image);
  185.     c->data = (unsigned long *)malloc(xsize*ysize*sizeof(long));
  186.     fastzoom(sdata,c->data,cxsize,cysize,xsize,ysize);
  187.     touchcanvas(c);
  188.     return c;
  189. }
  190.  
  191. int canvastoimage(c,name)
  192. canvas *c;
  193. char *name;
  194. {
  195.     return longstoimage(c->data,c->xsize,c->ysize,3,name);
  196. }
  197.  
  198. void freecanvas(c)
  199. canvas *c;
  200. {
  201.     if(c) {
  202.     myfree(c->data);
  203.     if(c->undo)
  204.         freeundo(c);
  205.     myfree(c);
  206.     
  207.     }
  208. }
  209.  
  210. canvas *clonecanvas(c)
  211. canvas *c;
  212. {
  213.     canvas *cc;
  214.  
  215.     cc = newcanvas(c->xsize,c->ysize);
  216.     canvascopy(c,cc);
  217.     cc->isdirty = c->isdirty;
  218.     cc->dirt = c->dirt;
  219.     cc->strokeno = c->strokeno;
  220.     cc->undo = 0;
  221.     return cc;
  222. }
  223.  
  224. void canvasflushfunc(c,func)
  225. canvas *c;
  226. int (*func)();
  227. {
  228.     c->flushfunc = func;
  229. }
  230.  
  231. void flushcanvas(c)
  232. canvas *c;
  233. {
  234.     if(c->isdirty) {
  235.     if(c->flushfunc) 
  236.         c->flushfunc(c);
  237.     c->isdirty = 0;
  238.     }
  239. }
  240.  
  241. void canvascopy(c,cc)
  242. canvas *c, *cc;
  243. {
  244.     bcopy(c->data,cc->data,c->xsize*c->ysize*sizeof(unsigned long));
  245. }
  246.  
  247. void touchcanvas(c)
  248. canvas *c;
  249. {
  250.     c->isdirty = 1;
  251.     c->dirt = c->area;
  252. }
  253.  
  254. unsigned long samplecanvas(c,pos,dofilter)
  255. canvas *c;
  256. vect *pos;
  257. int dofilter;
  258. {
  259.     int xpos, ypos;
  260.  
  261.     if(dofilter) {
  262.     xpos = ((c->xsize-0.01)*pos->x)+qrand();
  263.     ypos = ((c->ysize-0.01)*pos->y)+qrand();
  264.     } else {
  265.     xpos = ((c->xsize-0.01)*pos->x);
  266.     ypos = ((c->ysize-0.01)*pos->y);
  267.     }
  268.     if(xpos<0)
  269.     xpos = 0;
  270.     if(ypos<0)
  271.         ypos = 0;
  272.     if(xpos>=c->xsize)
  273.         xpos = c->xsize-1;
  274.     if(ypos>=c->ysize)
  275.         ypos = c->ysize-1;
  276.     return c->data[c->xsize*ypos+xpos];
  277. }
  278.  
  279. void markdirty(c,r,add)
  280. canvas *c;
  281. rct *r;
  282. int add;
  283. {
  284.     if(r) {
  285.     if(c->isdirty) {
  286.         rctunion(&c->dirt,r,&c->dirt);
  287.     } else {
  288.         c->dirt = *r;
  289.     }
  290.     c->isdirty = 1;
  291.     }
  292.     c->strokeno+=add;
  293. }
  294.  
  295. /*
  296.  *    drawing functions follow
  297.  *
  298.  */
  299. void clearcanvas(c)
  300. canvas *c;
  301. {
  302.     int n;
  303.     unsigned long *lptr, curc;
  304.  
  305.     saverect(c,&c->area);
  306.     n = c->xsize*c->ysize;
  307.     lptr = c->data;
  308.     curc = getcurcolor();
  309.     curc |= 0xff000000;
  310.     while(n) {
  311.     if(n>=8) {
  312.         lptr[0] = curc;
  313.         lptr[1] = curc;
  314.         lptr[2] = curc;
  315.         lptr[3] = curc;
  316.         lptr[4] = curc;
  317.         lptr[5] = curc;
  318.         lptr[6] = curc;
  319.         lptr[7] = curc;
  320.         lptr += 8;
  321.         n -= 8;
  322.     } else {
  323.         *lptr++ = curc;
  324.         n--;
  325.     }
  326.     }
  327.     touchcanvas(c);
  328. }
  329.  
  330. framecanvas(c)
  331. canvas *c;
  332. {
  333.     int n, xsize;
  334.     unsigned long *lptr1, *lptr2, curc;
  335.  
  336.     saverect(c,&c->area);
  337.     curc = getcurcolor();
  338.     curc |= 0xff000000;
  339.  
  340.     xsize = c->xsize;
  341.     lptr1 = c->data;
  342.     lptr2 = c->data+(xsize*(c->ysize-1));
  343.     n = xsize;
  344.     while(n--) {
  345.     *lptr1++ = curc;
  346.     *lptr2++ = curc;
  347.     }
  348.     lptr1 = c->data;
  349.     lptr2 = c->data+(xsize-1);
  350.     n = c->ysize;
  351.     while(n--) {
  352.     *lptr1 = curc;
  353.     *lptr2 = curc;
  354.     lptr1 += xsize;
  355.     lptr2 += xsize;
  356.     }
  357.     touchcanvas(c);
  358. }
  359.  
  360. /*
  361.  *    canvas zoomed copy code follows
  362.  *
  363.  */
  364. static zoom *rz, *gz, *bz;
  365. static int sdx, sdy;
  366. static canvas *srccan;
  367. static rct *srcrct;
  368.  
  369. static getr(buf,y)
  370. short *buf;
  371. int y;
  372. {
  373.     unsigned char *ptr;
  374.     int x;
  375.  
  376.     ptr = (unsigned char *)(srccan->data+
  377.             ((srcrct->ymin+y)*srccan->xsize+srcrct->xmin));
  378.     ptr = ptr+3;
  379.     for(x=0; x<sdx; x++) {
  380.     *buf++ = *ptr;
  381.     ptr += 4;
  382.     }
  383. }
  384.  
  385. static getg(buf,y)
  386. short *buf;
  387. int y;
  388. {
  389.     unsigned char *ptr;
  390.     int x;
  391.  
  392.     ptr = (unsigned char *)(srccan->data+
  393.             ((srcrct->ymin+y)*srccan->xsize+srcrct->xmin));
  394.     ptr = ptr+2;
  395.     for(x=0; x<sdx; x++) {
  396.     *buf++ = *ptr;
  397.     ptr += 4;
  398.     }
  399. }
  400.  
  401. static getb(buf,y)
  402. short *buf;
  403. int y;
  404. {
  405.     unsigned char *ptr;
  406.     int x;
  407.  
  408.     ptr = (unsigned char *)(srccan->data+
  409.             ((srcrct->ymin+y)*srccan->xsize+srcrct->xmin));
  410.     ptr = ptr+1;
  411.     for(x=0; x<sdx; x++) {
  412.     *buf++ = *ptr;
  413.     ptr += 4;
  414.     }
  415. }
  416.  
  417. void copyto(scan,dcan)
  418. canvas *scan;
  419. canvas *dcan;
  420. {
  421.     copycanvas(scan,&scan->area,dcan,&dcan->area,TRIANGLE);
  422.     flushcanvas(dcan);
  423. }
  424.  
  425. canvas *subcanvas(c,x1,x2,y1,y2)
  426. int x1, x2, y1, y2;
  427. {
  428.     int dx, dy;
  429.     canvas *subcan;
  430.     rct srct;
  431.  
  432.     if(x2<x1 || y2<y1) {
  433.      fprintf(stderr,"subcanvas: bad args\n");
  434.      exit(1);
  435.     }
  436.     dx = x2-x1+1;
  437.     dy = y2-y1+1;
  438.  
  439.     srct.xmin = x1;
  440.     srct.xmax = x2;
  441.     srct.ymin = y1;
  442.     srct.ymax = y2;
  443.  
  444.     subcan = newcanvas(dx,dy);
  445.     copycanvas(c,&srct,subcan,&subcan->area,IMPULSE);
  446.     return subcan;
  447. }
  448.  
  449. void copycanvas(scan,srct,dcan,drct,filter)
  450. canvas *scan;
  451. rct *srct;
  452. canvas *dcan;
  453. rct *drct;
  454. int filter;
  455. {
  456.     int ddx, ddy;
  457.     int sy, dy, lasty;
  458.     unsigned long *sptr, *dptr;
  459.     short *rs, *gs, *bs;
  460.     short *rsp, *gsp, *bsp;
  461.     int x, ncopy, basecopy;
  462.     rct dirt;
  463.  
  464.     sdx = srct->xmax-srct->xmin+1;
  465.     sdy = srct->ymax-srct->ymin+1;
  466.     ddx = drct->xmax-drct->xmin+1;
  467.     ddy = drct->ymax-drct->ymin+1;
  468.     saverect(dcan,drct);
  469.     if(sdx == ddx && sdy == ddy) {     /* clips to dest canvas */
  470.     ncopy = ddx;
  471.     if(drct->xmin<0) {
  472.         basecopy = (-drct->xmin);
  473.      } else
  474.         basecopy = 0;
  475.     ncopy -= basecopy;
  476.     if(drct->xmax>=dcan->xsize)
  477.         ncopy -= ( drct->xmax-(dcan->xsize-1));
  478.     if(ncopy>0) {
  479.         sy = srct->ymin;
  480.         dy = drct->ymin;
  481.         sptr = scan->data+(sy*scan->xsize+srct->xmin);
  482.         dptr = dcan->data+(dy*dcan->xsize+drct->xmin+basecopy);
  483.         while(sy<=srct->ymax) {
  484.         if(dy>=0 && dy<dcan->ysize)
  485.             bcopy(sptr,dptr,ncopy*sizeof(long));
  486.         sptr += scan->xsize;
  487.         dptr += dcan->xsize;
  488.         sy++;
  489.         dy++;
  490.         }
  491.      }
  492.     markdirty(dcan,drct,1);
  493.    } else{
  494.         srccan = scan;
  495.     srcrct = srct;
  496.     rz = newzoom(getr,sdx,sdy,ddx,ddy,filter,1.0);
  497.     gz = newzoom(getg,sdx,sdy,ddx,ddy,filter,1.0);
  498.     bz = newzoom(getb,sdx,sdy,ddx,ddy,filter,1.0);
  499.     rs = (short *)mymalloc(ddx*sizeof(short));
  500.     gs = (short *)mymalloc(ddx*sizeof(short));
  501.     bs = (short *)mymalloc(ddx*sizeof(short));
  502.     lasty = drct->ymin;
  503.     dirt.xmin = drct->xmin;
  504.     dirt.xmax = drct->xmax;
  505.     for(dy=drct->ymin; dy<=drct->ymax; dy++) {
  506.         getzoomrow(rz,rs,dy-drct->ymin);
  507.         getzoomrow(gz,gs,dy-drct->ymin);
  508.         getzoomrow(bz,bs,dy-drct->ymin);
  509.         dptr = dcan->data+(dy*dcan->xsize+drct->xmin);
  510.         rsp = rs;
  511.         gsp = gs;
  512.         bsp = bs;
  513.         x = ddx;
  514.         while(x) {
  515.         if(x>=8) {
  516.             dptr[0] = (rsp[0]<<0)+(gsp[0]<<8)+(bsp[0]<<16);
  517.             dptr[1] = (rsp[1]<<0)+(gsp[1]<<8)+(bsp[1]<<16);
  518.             dptr[2] = (rsp[2]<<0)+(gsp[2]<<8)+(bsp[2]<<16);
  519.             dptr[3] = (rsp[3]<<0)+(gsp[3]<<8)+(bsp[3]<<16);
  520.             dptr[4] = (rsp[4]<<0)+(gsp[4]<<8)+(bsp[4]<<16);
  521.             dptr[5] = (rsp[5]<<0)+(gsp[5]<<8)+(bsp[5]<<16);
  522.             dptr[6] = (rsp[6]<<0)+(gsp[6]<<8)+(bsp[6]<<16);
  523.             dptr[7] = (rsp[7]<<0)+(gsp[7]<<8)+(bsp[7]<<16);
  524.             dptr += 8;
  525.             rsp += 8;
  526.             gsp += 8;
  527.             bsp += 8;
  528.             x-=8;
  529.         } else {
  530.             *dptr++ = (*rsp<<0)+(*gsp<<8)+(*bsp<<16);
  531.             rsp++;
  532.             gsp++;
  533.             bsp++;
  534.             x--;
  535.         }
  536.         }
  537.         if((dy-lasty)==10) {
  538.         dirt.ymin = lasty;
  539.         dirt.ymax = dy;
  540.         markdirty(dcan,&dirt,1);
  541.         flushcanvas(dcan);
  542.         lasty = dy;
  543.         }
  544.         }
  545.     dirt.ymin = lasty;
  546.     dirt.ymax = dy-1;
  547.     markdirty(dcan,&dirt,1);
  548.     flushcanvas(dcan);
  549.  
  550.     freezoom(rz);
  551.     freezoom(gz);
  552.     freezoom(bz);
  553.     myfree(rs);
  554.     myfree(gs);
  555.     myfree(bs);
  556.     }
  557. }
  558.  
  559. /*
  560.  *    canvas printing code
  561.  *
  562.  */
  563. void printcanvas(c)
  564. canvas *c;
  565. {
  566.     mypercentdone(50.0);
  567.     canvastoimage(c,"/usr/tmp/pr.rgb");
  568.     system("printimage /usr/tmp/pr.rgb");
  569.     system("rm /usr/tmp/pr.rgb");
  570.     mypercentdone(100.0);
  571. }
  572.  
  573.